<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>压缩上传</title>
  </head>
  <body>
    <input type="file" id="upload" />
    <script>
      // 将图片转换为 base64
      function convertImageToBase64(file, cb) {
        let reader = new FileReader() // 实例化 - 读取文件内容
        reader.addEventListener('load', function (e) {
          const base64Image = e.target.result // 获取文件内容，等同于 reader.result
          cb(base64Image)
          reader = null
        })
        reader.readAsDataURL(file) // 读取 file 对象中的内容,触发addEventListener
      }

      // 压缩图片
      function compress(base64Image, cb) {
        let maxW = 1024
        let maxH = 1024
        const image = new Image()
        image.addEventListener('load', function () {
          let ratio // 压缩比
          let needCompress = false // 是否需要压缩
          // 如果图片宽度大于最大宽度，则需要压缩
          if (maxW < image.naturalWidth) {
            needCompress = true
            ratio = image.naturalWidth / maxW
            maxH = image.naturalHeight / ratio
          }
          // 如果图片高度大于最大高度，则需要压缩
          if (maxH < image.naturalHeight) {
            needCompress = true
            ratio = image.naturalHeight / maxH
            maxW = image.naturalWidth / ratio
          }
          // 如果图片不需要压缩，则设置最大宽度和最大高度
          if (!needCompress) {
            maxW = image.naturalWidth
            maxH = image.naturalHeight
          }
          const canvas = document.createElement('canvas') // 创建 canvas
          canvas.setAttribute('id', '__compress__') // 设置 canvas 的 id
          canvas.width = maxW // 设置 canvas 的宽度
          canvas.height = maxH // 设置 canvas 的高度
          const ctx = canvas.getContext('2d') // 获取 canvas 的上下文
          ctx.clearRect(0, 0, maxW, maxH) // 清除 canvas 的矩形区域
          ctx.drawImage(image, 0, 0, maxW, maxH) // 渲染图片
          const compressImage = canvas.toDataURL('image/jpeg', 0.9) // 将cvas输出成img格式,质量0.9
          cb(compressImage)
          canvas.remove() // 移除 canvas
        })
        image.src = base64Image // 将图片设置到 image 的 src 属性中
      }

      // 上传图片
      const ACCEPT = ['image/jpg', 'image/png', 'image/jpeg'] // 限定图片文件类型
      const MAXSIZE = 1024 * 1024 * 20 // 限定图片最大容量
      const upload = document.getElementById('upload') // 获取上传按钮
      // 监听上传按钮的 change 事件
      upload.addEventListener('change', function (e) {
        const file = e.target.files[0] // 获取文件
        if (!file) return // 如果文件不存在，则返回
        const { type: fileType, size: fileSize } = file // 获取文件类型和大小
        // 图片类型检查
        if (!ACCEPT.includes(fileType)) {
          alert('不支持上传该格式文件！')
          upload.value = ''
          return
        }
        // 图片大小检查
        if (fileSize > MAXSIZE) {
          alert('文件大小超出')
          upload.value = ''
          return
        }
        // 压缩文件
        convertImageToBase64(file, base64Image =>
          compress(base64Image, compressImage => {
            // 以下代码可以不用，只是为了查看压缩后的图片大小，进行对比
            const _image = new Image()
            _image.src = compressImage
            document.body.appendChild(_image)
          })
        )
      })
    </script>
  </body>
</html>
